/**
 * Copyright (C) 2012 Foxit Corporation.
 * All Rights Reserved.
 *
 * The following code is copyrighted and contains proprietary information and trade secrets of Foxit Corporation.
 * You can only redistribute files listed below to customers of your application, under a written SDK license agreement with Foxit.
 * You cannot distribute any part of the SDK to general public, even with a SDK license agreement.
 * Without SDK license agreement, you cannot redistribute anything.
 *
 * @file fpdfsecurity.h
 * @brief 	Header file for the PDF Security module.
 * @details	The Security Module is used for encrypting and decrypting PDF.<br>
 *			Currently, this module supports custom encryption and decryption, and public-key encryption and decryption.
 *			The callback mechanism provided in this module allow users to operate the PDF file.
 * @note	If you want to purchase Foxit GSDK license and use ANY of the following functions, please
 *			request for enabling Base Data module explicitly. 
 */
 
 /** 
 * @addtogroup FGSPDFSECURITY PDF Security
 * @brief Definitions and Methods in this module are included in fpdfsecurity.h.
 */
 
 /** @{*/

#ifndef __FGSPDFSECURITY__
#define __FGSPDFSECURITY__

#ifndef __FGSPDFBASE__
    #include "fpdfbase.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

/** 
 * @brief Structure for Custom Security Handler. 
 *
 * @details This structure holds a number of interfaces allowing application to use customized security handlers.<br>
 *		   A security handler is responsible for decrypting data and enforce document permissions.
 */
typedef struct _FGSPDFCustomSecurityHandler {

    /** @brief The size of the data structure. It must be set to <I>sizeof</I>(::FGSEPUBCryptoHandler). */
	UInt32  size;

	/** @brief The user-supplied data. */
	void *	clientData;
	
	/** @brief The callback function to startDecrypt. */
    void *  (*startDecrypt)(void *clientData, SInt32 objnum, SInt32 gennum);

	/** @brief The callback function to doDecrypt. */
    void    (*doDecrypt)(void *clientData, void *context, CFDataRef src_buf, CFMutableDataRef det_buf);

	/** @brief The callback function to finishDecrypt. */
    void	(*finishDecrypt)(void *clientData, void *context, CFMutableDataRef det_buf);
    
	/** @brief The callback function to getEncryptSize. */
    SInt32  (*getEncryptSize)(void *clientData, SInt32 objnum, SInt32 version, CFDataRef src_buf);

	/** @brief The callback function to encryptContent. */
    void 	(*encryptContent)(void *clientData, SInt32 objnum, SInt32 version, CFDataRef src_buf, CFMutableDataRef det_buf);
} FGSPDFCustomSecurityHandler;

/** 
 * @brief 	Create custom security of the PDF document.
 *
 * @param[in] customHandler             Reference to the FGSPDFCustomSecurityHandler.
 * @param[in] filter                    The filter of the encryption.	
 *  
 * @return	Reference to the custom security.
 */
FGSPDFSecurityRef FGSPDFSecurityCreateCustomSecurity(FGSPDFCustomSecurityHandler *customHandler, CFStringRef filter);

/** 
 * @brief 	Create PKI security of the PDF document.
 *  
 * @return	Reference to the PKI security.
 */
FGSPDFSecurityRef FGSPDFSecurityCreatePKISecurity();

/** 
 * @brief 	Set cipher key of the PKI security.
 *
 * @param[in] security                  Reference to the PKI security.
 * @param[in] cipher                    Cipher identifier.
 * @param[in] key_bytes                 The length of key for AES or RC4 algorithm, should be 16 or 32.
 *  
 * @return	::kFGSErrorSuccess means success.<br>
 *			 For more definitions please see enum definitions <b>FGSErrorRet</b>.
 */
FGSErrorRet	FGSPDFSecuritySetPKICipher(FGSPDFSecurityRef security, FGSCipherFlag nCipher, SInt32 key_bytes); 

/** 
 * @brief 	Add envelope of the PKI security.
 *
 * @param[in]	security    			Reference to the PKI security.
 * @param[in]	encryptedEnvelope    	Reference to the certificate encrypted envelope data.
 * @param[in]	decryptedEnvelope    	Reference to the certificate original envelope data. The first 20 bytes are seed, and the last 4 bytes are permissions.
 *  
 * @return	::kFGSErrorSuccess means success.<br>
 *			 For more definitions please see enum definitions <b>FGSErrorRet</b>.
 */
FGSErrorRet FGSPDFSecurityAddPKIEnvelope(FGSPDFSecurityRef security, CFDataRef encryptedEnvelope, CFDataRef decryptedEnvelope);

/** 
 * @brief 	Count the envelope of the PKI security.
 *
 * @param[in] document                  Reference to the document.
 *  
 * @return	The count of the envelope.
 */
SInt32 FGSPDFSecurityCountPKIEnvelope(FGSPDFDocumentRef document);

/** 
 * @brief 	Get the envelope of the PKI security.
 *
 * @param[in] document                  Reference to the document.
 * @param[in] index                     The index of the PKI Security.
 * @param[in,out]data                   The envelope of the specific index.
 * 
 * @return	None.
 */
void FGSPDFSecurityCopyPKIEnvelope(FGSPDFDocumentRef document, SInt32 index, CFMutableDataRef data);

/** 
 * @brief 	Set the decryptedEnvelope of the PKI security.
 *
 * @param[in] document                  Reference to the document.
 * @param[in] index                     The index of the PKI Security.
 * @param[in] decryptedEnvelope         The decrypted envelope of the PKI Security.
 * 
 * @return	   ::kFGSErrorSuccess means success.<br>
 *			 For more definitions please see enum definitions <b>FGSErrorRet</b>.
 */
FGSErrorRet	FGSPDFSecuritySetDecryptedEnvelope(FGSPDFDocumentRef document, SInt32 index, CFDataRef decryptedEnvelope);

/** 
 * @brief 	Create standard security of the PDF document.
 *
 * @param[in] userPassword              The user password.				
 * @param[in] ownerPassword             The owner password.
 * @param[in] cipher                    Cipher identifier.
 * @param[in] key_bytes                 The length of key for AES or RC4 algorithm, should be 16 or 32.
 *  
 * @return	Reference to the custom security.
 */
FGSPDFSecurityRef FGSPDFSecurityCreateStdSecurity(CFStringRef userPassword, CFStringRef ownerPassword, SInt32 cipher, SInt32 key_bytes);

/** 
 * @brief 	Set security of the document.
 *
 * @param[in] document                  Reference to the document.
 * @param[in] security                  Reference to a security of the document.
 * 
 * @return	   ::kFGSErrorSuccess means success.<br>
 *			 For more definitions please see enum definitions <b>FGSErrorRet</b>.
 */
FGSErrorRet FGSPDFSecuritySetDocSecurity(FGSPDFDocumentRef document, FGSPDFSecurityRef security);

/** 
 * @brief 	Set encrypt metadata of the security.
 *
 * @param[in] security                  Reference to a security..
 * @param[in] encrypt                   Whether the data is encrypted.
 * 
 * @note     Custom security can be set metadata.
 * @return	   ::kFGSErrorSuccess means success.<br>
 *			 For more definitions please see enum definitions <b>FGSErrorRet</b>.
 */
FGSErrorRet FGSPDFSecurityEncryptMetadata(FGSPDFSecurityRef security, Boolean encrypt);

/** 
 * @brief 	Set permissions of the security.
 *
 * @param[in] security                  Reference to a security.
 * @param[in] permissions               The permissions of the security.
 * 
 * @note     Custom security can be set permissions
 * @return	   ::kFGSErrorSuccess means success.<br>
 *			 For more definitions please see enum definitions <b>FGSErrorRet</b>.
 */
FGSErrorRet	FGSPDFSecuritySetPermissions(FGSPDFSecurityRef security, SInt32 permissions);

/** 
 * @brief 	Create foxit DRM security of the PDF document.
 *
 * @param[in] filter                    The filter of the encryption.
 * @param[in] cipher                    Cipher identifier.
 * @param[in] key                       The key information of the foxit DRM security. 
 *  
 * @return	Reference to the foxit DRM security.
 */
FGSPDFSecurityRef FGSPDFSecurityCreateFoxitDRMSecurity(CFStringRef filter, FGSCipherFlag cipher, CFDataRef key);

/** 
 * @brief 	Set the identity of the foxit DRM security.
 *
 * @param[in] security                  Reference to the foxit DRM security..
 * @param[in] identity                  The identity of the foxit DRM security.
 * 
 * @return	   ::kFGSErrorSuccess means success.<br>
 *			 For more definitions please see enum definitions <b>FGSErrorRet</b>.
 */
FGSErrorRet	FGSPDFSecuritySetFoxitDRMSecurityIdentity(FGSPDFSecurityRef security, CFStringRef identity);

/** 
 * @brief 	Verify the security is the foxit DRM security or not.
 *
 * @param[in]	security                Reference to a security.
 * 
 * @return	   True means foxit DRM security, false means not.
 */
Boolean	FGSPDFSecurityVerifyFoxitDRMSecurity(FGSPDFSecurityRef security);

/** 
 * @brief 	Destroy all the security setting of the PDF document, the output PDF will be decrypted.
 *
 * @param[in]	security                Reference to a security.
 *
 * @return	::kFGSErrorSuccess means success.<br>
 *			 For more definitions please see enum definitions <b>FGSErrorRet</b>.
 */
FGSErrorRet FGSPDFSecurityDestroySecurity(FGSPDFSecurityRef security);

/** 
 * @brief 	Remove all the security setting of the PDF document, the output PDF will be decrypted.
 *
 * @param[in] doc                       Reference to a document.
 * @param[in] fileWrite                 Pointer to a custom file write structure.
 *
 * @return	::FS_kFGSErrorSuccess means success.<br>
 *			 For more definitions please see macro definitions <b>FGSErrorRet</b>.
 */
FGSErrorRet FGSPDFSecurityRemoveSecurity(FGSPDFDocumentRef doc, CFStringRef file);

/** 
 * @brief 	Get level of password: no password, user password, or owner password.
 *
 * @param[in] doc                       Reference to a document.
 *
 * @return	 The password level.<br>
 *			<ul>
 *			<li>0 : no password</li>
 *			<li>1 : user password</li>
 *			<li>2 : owner password</li>
 *			</ul>
 */
SInt32 FGSPDFSecurityGetPasswordLevel(FGSPDFDocumentRef doc);

/**
 * @brief Check if the document is encrypted.
 *
 * @param[in] document                  Reference to a pdf document.		
 *
 * @return	The flag whether the document is encrypted.
 *
 */
Boolean FGSPDFSecurityIsEncrypted(FGSPDFDocumentRef document); 

/**
 * @brief Get the filter of the encryption.
 *
 * @param[in] document                  Reference to a pdf document.
 *
 * @return	The filter of the encryption.
 *
 */
CFStringRef FGSPDFSecurityCopyEncryptFilter(FGSPDFDocumentRef document); 
    
/**
 * @brief Check if the document is encrypted in the standard way.
 *
 * @param[in] document                  Reference to a pdf document.
 *
 * @return	The flag whether is the standard encryption.
 *
 */
Boolean FGSPDFSecurityIsStdEncrypted(FGSPDFDocumentRef document); 
    
/**
 * @brief Check if the user is the owner of the document.
 *
 * @param[in]		document			Reference to a pdf document.
 *
 * @return	The flag whether is the owner of the pdf document.
 *
 */
Boolean FGSPDFSecurityIsOwner(FGSPDFDocumentRef document); 

/**
 * @brief check whether the password for the standard encryption is correct.
 *
 * @param[in]		document			Reference to a pdf document.
 * @param[in]		password			The byte string password.
 *
 * @return	The flag whether is correct or not.
 *
 */
Boolean FGSPDFSecurityCheckStdPassword(FGSPDFDocumentRef document, CFDataRef password);

#ifdef __cplusplus
};
#endif

#endif // __FGSPDFSECURITY__
/**@}*/

